; usa funciones del archivo c-lisp.lsp... pero no importa ya que estan en memoria..

(defun evaluar (prg mem)
    (if (atom prg) (if (ESVARIABLE prg mem) (BUSCAR prg mem) PRG)
        (evaluarExpresion (armarExpresion prg mem))
    )
)

(defun armarExpresion (expr mem)
    (if (null expr) NIL
        (cond
            ;Si la cabeza de 'expr' no es atomo, separamos la cabeza de la cola, y nos llamamos recursivamente para cabeza y cola
            ( (not (atom (car expr))) (cons (list (armarExpresion (car expr) mem)) (armarExpresion (cdr expr) mem)) )
            
            ;Si es una variable buscamos su valor en memoria y la suplantamos por el en la expresion
            ( (ESVARIABLE (car expr) mem) (cons (BUSCAR (car expr) mem) (armarExpresion (cdr expr) mem)) )
            
            ;Si es un operador, es op de C, debemos traducirlo a op de lisp (no todos necesitan traduccion)
            ( (ESOPER (car expr)) (cons (traducirOp (car expr)) (armarExpresion (cdr expr) mem)) )
            
            ;Si no es nada de lo anterior, es constante y lo dejamos tal cual esta (seguimos recursivamente sobre la cola).
            ( T (cons (car expr) (armarExpresion (cdr expr) mem)) )
        )
    )
)

; evalua la epresion: en realidad se fija si es atomo, sino el que evalua realmente es evaluarExpresionAux
(defun evaluarExpresion (lista)
    (if (eq (length lista) 1)
        (if (atom (car lista))
            (car lista) ; si car lista es atomo, no necesita ser evaluada (solo  puede ser una cte)
            (filtroSalida (evaluarExpresionAux (convertToLisp lista))) ; si no es atomo, llamamos a evaluarExpresionAux
        )
        (filtroSalida (evaluarExpresionAux (convertToLisp lista)))
    )
)

;busca la primera (parantesis mas interntos y a la izquierda) expresion a evaluar de 'lista',y la evalua
(defun evaluarExpresionAux (lista)
    (if (null lista)
        nil
        (if (atom (car lista))
            (eval lista)
            (evaluarExpresionAux (car lista))
        )
    )
)

; Estandariza la salida como en C --> Devuelve 0 en vez de NIL, y 1 en vez de T
(defun filtroSalida (resultado)
    (cond
        ((equal resultado NIL) 0)
        ((equal resultado T) 1)
        (T resultado)
    )
)
